# -*-coding:utf-8-*-
'''

3.type definition:
                >>>>>>>>>>>>>>>>>>>>>
    > typedef   > type specifier    >  dec_list > ;

7.type specifier:
    >>>>>>>>>>>>>
                > base_type                     >
    > sign_flag >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
    >>>>>>>>>>>>> struct_list (struct spec)     >
    >>>>>>>>>>>>> enum spec                     >

17.enum spec
    > enum  > identifier    >>>>>>>>>>>>>>>>>>>>>>>>>>
            >>>>>>>>>>>>>>>>> { > enumerator    > } >
                                < ,             <

18.enumerator:
    > identifier    >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
                    > = > constant expression   >

19.struct spec:
    > struct    > identifier    >>>>>>>>>>>>>>>>>>>>>>>>>>>>>
    > union     >>>>>>>>>>>>>>>>> { > struct dec    >  }    >
                                    < ;             <

20.struct dec:
    > type specifier    > declarator    >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
                        >>>>>>>>>>>>>>>>> : > constant expression   >               ...to do
                        < ,                                         <               ...to do

24.constant expression:
    > int constant                                                                                      >
    > char constant                                                                                     >
    > enum constant                                                                                     >
    > sizeof expression                                                                                 >
    > (                     > constant expression   > )                                                 >
    > constant expression   > binop A               > constant expression                               >
    > -                     > constant expression                                                       >
    > ~                     >
    > constant expression   > ?                     > constant expression   > : > constant expression   >

8.dec_list:
    > declarator    >
    < ,             <

9.declarator:
    > identifier                                    >
    > ( > declarator    > )                         >
    > * > declarator                                >
    > declarator    > ( > )                         >
    > declarator    > [ >>>>>>>>>>>>>>>>>>>>>>> ]   >
                        > constant expression >
'''
import model
import re
from c_code_base_analyzer import eat_units, kick_units, print_comment
from c_code_base_analyzer import c_code_reader

size_dic = {
    "U8": 1,
    "S8": 1,
    "U16": 2,
    "S16": 2,
    "U32": 4,
    "S32": 4,
    "U64": 8,
    "S64": 8
}


def sizeof(x):
    return size_dic[x]

    


class type_definition_analyzer(c_code_reader):

    brace_cnt_in_struct = 0
    member_type_tmp = ""
    def struct_in_getmember(self, line):
        
        line_left, is_struct_result = eat_units(line.strip(), "union")
        if not is_struct_result:
            line_left, is_struct_result = eat_units(line.strip(), "struct")
        line_left, result = kick_units(line_left, "{")
        if result is True:
            self.brace_cnt_in_struct += 1
            if self.brace_cnt_in_struct == 1:
                return False
            else:
                self.member_type_tmp += line
                return True
        line_left, result = eat_units(line.strip(), "}")
        if result is True:
            self.brace_cnt_in_struct -= 1
            if self.brace_cnt_in_struct < 0:
                self.brace_cnt_in_struct = 0
            if self.brace_cnt_in_struct == 1:
                self.member_type_tmp += line
        if self.brace_cnt_in_struct > 1:
            self.member_type_tmp += line
            return True
        if is_struct_result and line_left.strip() == "":
            return True



        return False

    type_analyzer_handler = None
    type_state_handler_dic = {}
    type_analyzer_dic = {}

    def type_definition_init(self):
        self.type_analyzer_dic = {
            "typedef": self.type_specifier,
            "struct": self.struct_analyzer,
            "enum": self.enum_analyzer,
            "union": self.union_analyzer
        }
        self.type_state_handler_dic = {
            "get_struct_member": self.struct_analyzer,
            "get_type_struct_member": self.type_struct_analyzer,
            "get_enum_member": self.enum_analyzer,
            "get_type_enum_member": self.type_enum_analyzer,
            "get_union_member": self.union_analyzer,
            "get_type_union_member": self.type_union_analyzer
        }

    def member_tmp_dic_update(self, line_left):
        if line_left.find(';')>0:
            line_left = line_left[:line_left.find(';')].strip() + ';'
            ret = re.match(r'(.*)\s(.*);', line_left.strip())
            if ret is not None:
                self.member_tmp_dic[ret.group(2)] = ret.group(
                    1).strip()
        return ""
    '''
    19.struct spec:
    > struct    > identifier    >>>>>>>>>>>>>>>>>>>>>>>>>>>>>
    > union     >>>>>>>>>>>>>>>>> { > struct dec    >  }    >
                                    < ;             <
    '''
    type_tmp_name = ""
    member_tmp_dic = {}

    def type_struct_analyzer(self, line_left):
        line_left = line_left.strip()
        if self.compile_flag is True:
            if self.struct_in_getmember(line_left):
                return ""
            elif self.member_type_tmp != "":
                line_left = self.member_type_tmp
                self.member_type_tmp = ""

            # first time we call this function
            if self.current_state == "":
                line_left = line_left[:line_left.find('{')].strip()
                if line_left != "":
                    self.type_tmp_name = "struct" + " " + line_left
                    self.current_state = "get_type_struct_member"
                    self.current_handler = self.type_struct_analyzer
                    return ""
                else:
                    self.current_state = "get_type_struct_member"
                    self.current_handler = self.type_struct_analyzer
                    self.type_tmp_name = "struct "
                    return ""
            elif line_left != "":
                # seems we finish analyzed this struct
                if line_left.strip()[0] == '}' or self.current_state == "get_def_dics"\
                        or self.current_state == "finished_def":
                    line_left, result = eat_units(line_left, "}")
                    if line_left != "":
                        if (line_left[-1] == ';'):
                            if self.type_tmp_name == "struct ":
                                self.type_tmp_name = self.type_tmp_name + \
                                    line_left[:-1]
                            if not self.dic_temp:
                                if self.type_tmp_name != line_left[:-1]:
                                    typedef_dic = {
                                        line_left[:-1].strip(): self.type_tmp_name
                                    }
                                    print_comment("type_info.type_def_list.update")
                                    self.module_info.type_info.type_def_list.update(
                                        typedef_dic)
                            else:
                                if self.type_tmp_name != line_left[:-1]:
                                    typedef_dic = {
                                        line_left[:-1].strip(): self.type_tmp_name
                                    }
                                    print_comment("type_info.type_def_list.update")
                                    '''
                                    to add the last dic
                                    '''
                                    self.module_info.type_info.type_def_list.update(
                                        typedef_dic)
                                '''
                                to add the dics we have
                                '''
                                for key, value in self.dic_temp.items():
                                    print_comment("type_info.type_def_list.update")
                                    self.module_info.type_info.type_def_list.update(
                                        {key: value})
                            struct_unit = model.struct_info(
                                name=self.type_tmp_name,
                                is_public=False,
                                member_list=self.member_tmp_dic)

                            # self.dic_temp[self.type_tmp_name] = self.member_tmp_dic
                            print_comment("type_info.struct_list.append")
                            self.module_info.type_info.struct_list.append(
                                struct_unit)

                            # init temp parameters and set the current handler to None
                            self.type_tmp_name = ""
                            self.member_tmp_dic = {}
                            self.current_handler = None
                            self.dic_temp = {}
                            self.current_state = ""
                        else:
                            if line_left.find(',') > 0:
                                for dec in line_left.split(','):
                                    if dec != "":
                                        self.dic_temp[dec] = self.type_tmp_name
                                self.current_state = "get_def_dics"
                            else:
                                self.crashed = True
                    else:
                        self.current_state = "finished_def"
                    return ""

                else:
                    line_left, result = eat_units(line_left, "{")
                    line_left = self.member_tmp_dic_update(line_left)
                    if result is True:
                        return ""

        return line_left

    union_tmp_list = []

    def type_union_analyzer(self, line_left):
        line_left = line_left.strip()
        if self.compile_flag is True:
            if self.struct_in_getmember(line_left):
                return ""
            elif self.member_type_tmp != "":
                line_left = self.member_type_tmp
                self.member_type_tmp = ""
            # first time we call this function
            if self.current_state == "":
                line_left = line_left[:line_left.find('{')].strip()
                if line_left != "":
                    self.type_tmp_name = "union" + " " + line_left
                    self.current_state = "get_type_union_member"
                    self.current_handler = self.type_union_analyzer
                    return ""
                else:
                    self.current_state = "get_type_union_member"
                    self.current_handler = self.type_union_analyzer
                    self.type_tmp_name = "union "
            if line_left != "":
                # seems we finish analyzed this union
                if line_left[0] == '}' or self.current_state == "get_def_dics":
                    line_left, result = eat_units(line_left, "}")
                    if (line_left[-1] == ';'):
                        self.type_tmp_name = self.type_tmp_name + line_left[:-1]
                        if not self.dic_temp:
                            if self.type_tmp_name != line_left[:-1]:
                                typedef_dic = {
                                    line_left[:-1]: self.type_tmp_name
                                }
                                print_comment("type_info.type_def_list.update")
                                self.module_info.type_info.type_def_list.update(
                                    typedef_dic)
                        else:
                            if self.type_tmp_name != line_left[:-1]:
                                typedef_dic = {
                                    line_left[:-1]: self.type_tmp_name
                                }
                                print_comment("type_info.type_def_list.update")
                                self.module_info.type_info.type_def_list.update(
                                    typedef_dic)

                            for key, value in self.dic_temp.items():
                                print_comment("type_info.type_def_list.update")
                                self.module_info.type_info.type_def_list.update(
                                    {key: value})

                        union_unit = model.union_info(
                            name=self.type_tmp_name,
                            is_public=False,
                            union_list=self.union_tmp_list)

                        # self.dic_temp[self.type_tmp_name] = self.member_tmp_dic
                        print_comment("type_info.union_list.append")
                        self.module_info.type_info.union_list.append(
                            union_unit)

                        # init temp parameters and set the current handler to None
                        self.type_tmp_name = ""
                        self.member_tmp_dic = {}
                        self.union_tmp_list = []
                        self.current_handler = None
                        self.dic_temp = {}
                        self.current_state = ""
                    else:
                        if line_left.find(',') > 0:
                            for dec in line_left.split(','):
                                if dec != "":
                                    self.dic_temp[dec] = self.type_tmp_name
                            self.current_state = "get_def_dics"
                        else:
                            self.crashed = True
                    return ""

                else:
                    line_left, result = eat_units(line_left, "{")
                    if (line_left == ""):
                        return ""
                    line_left, result = eat_units(line_left, "}")
                    if result is True:
                        if line_left[-1] == ';' and self.member_tmp_dic != {}:
                            self.union_tmp_list.append(
                                {line_left[:-1]: self.member_tmp_dic})
                            self.member_tmp_dic = {}
                            return ""

                    line_left, reuslt, type_str = self.find_type(line_left)
                    if reuslt is True and line_left[-1] == ';':
                        self.member_tmp_dic[line_left[:-1]] = type_str
                        return ""
                    elif self.member_tmp_dic != {}:
                        self.union_tmp_list.append(self.member_tmp_dic)
                        self.member_tmp_dic = {}
                        return ""
                    elif line_left[-1] == ';':
                        line_left = line_left[:line_left.find(';')].strip() + ';'
                        ret = re.match(r'(.*)\s(.*);', line_left.strip())
                        if ret is not None:
                            self.union_tmp_list.append(
                                {ret.group(2): ret.group(1).strip()})
                        else:
                            self.crashed = True
                    else:
                        return ""
                    if result is True:
                        return ""

        return line_left

    '''
    17.enum spec
        > enum  > identifier    >>>>>>>>>>>>>>>>>>>>>>>>>>
                >>>>>>>>>>>>>>>>> { > enumerator    > } >
                                    < ,             <

    18.enumerator:
        > identifier    >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
                        > = > constant expression   >
    '''
    dic_str_temp = ""

    def type_enum_analyzer(self, line_left):
        line_left = line_left.strip()
        if self.compile_flag is True:
            # first time we call this function
            if self.current_state == "":
                line_left = line_left[:line_left.find('{')].strip()
                if line_left != "":
                    line_left = " " + line_left
                self.type_tmp_name = "enum" + line_left
                self.current_state = "get_type_enum_member"
                self.current_handler = self.type_enum_analyzer
                return ""
            # seems we finish analyzed this enum
            elif line_left != "":
                if line_left[0] == '}' or self.current_state == "get_def_dics":
                    line_left, dont_care_result = eat_units(line_left, "}")
                    if (line_left[-1] == ';'):
                        if self.type_tmp_name == "enum":
                            self.type_tmp_name = self.type_tmp_name + " " + \
                                line_left[:-1]
                        if not self.dic_temp:
                            if self.type_tmp_name != line_left[:-1]:
                                typedef_dic = {
                                    line_left[:-1]: self.type_tmp_name
                                }
                                print_comment("type_info.type_def_list.update")
                                self.module_info.type_info.type_def_list.update(
                                    typedef_dic)
                        else:
                            if self.type_tmp_name != line_left[:-1]:
                                typedef_dic = {
                                    line_left[:-1]: self.type_tmp_name
                                }
                                print_comment("type_info.type_def_list.update")
                                self.module_info.type_info.type_def_list.update(
                                    typedef_dic)

                            for key, value in self.dic_temp.items():
                                print_comment("type_info.type_def_list.update")
                                self.module_info.type_info.type_def_list.update(
                                    {key: value})

                        enum_value = 0
                        for line in self.dic_str_temp.split(','):
                            if line.find('=') > 0:
                                key = line.split('=')[0].strip()
                                value_str = line.split('=')[1].strip()
                                enum_value = eval(value_str)
                                self.member_tmp_dic[key] = enum_value
                            else:
                                self.member_tmp_dic[line.strip()] = enum_value
                                enum_value += 1

                        enum_unit = model.struct_info(
                            name=self.type_tmp_name,
                            is_public=False,
                            member_list=self.member_tmp_dic)

                        # self.dic_temp[self.type_tmp_name] = self.member_tmp_dic
                        print_comment("type_info.enum_list.append")
                        self.module_info.type_info.enum_list.append(enum_unit)

                        # init temp parameters and set the current handler to None
                        self.type_tmp_name = ""
                        self.member_tmp_dic = {}
                        self.current_handler = None
                        self.dic_temp = {}
                        self.current_state = ""
                        self.dic_str_temp = ""
                    else:
                        if line_left.find(',') > 0:
                            for dec in line_left.split(','):
                                if dec != "":
                                    self.dic_temp[dec] = self.type_tmp_name
                            self.current_state = "get_def_dics"
                        else:
                            self.crashed = True
                    return ""
                else:
                    line_left, result = eat_units(line_left, "{")
                    self.dic_str_temp += line_left
                    return ""
        return line_left

    def enum_analyzer(self, line_left):
        line_left = line_left.strip()
        if self.compile_flag is True:
            # first time we call this function
            if self.current_state == "":
                if line_left == "{":
                    self.type_tmp_name = "enum"
                else:
                    if line_left.find(' ') > 0:
                        line_left = line_left[:line_left.find(' ')]
                    self.type_tmp_name = "enum " + \
                        line_left.strip()
                self.current_state = "get_enum_member"
                self.current_handler = self.enum_analyzer
                return ""
            # seems we finish analyzed this enum
            elif line_left != "":
                if line_left[0] == '}' or self.current_state == "get_def_dics":
                    line_left, dont_care_result = eat_units(line_left, "}")
                    if (line_left[-1] == ';'):
                        enum_value = 0
                        for line in self.dic_str_temp.split(','):
                            if line.find('=') > 0:
                                key = line.split('=')[0].strip()
                                value_str = line.split('=')[1].strip()
                                enum_value = eval(value_str)
                                self.member_tmp_dic[key] = enum_value
                            else:
                                self.member_tmp_dic[line.strip()] = enum_value
                                enum_value += 1

                        enum_unit = model.struct_info(
                            name=self.type_tmp_name,
                            is_public=False,
                            member_list=self.member_tmp_dic)

                        # self.dic_temp[self.type_tmp_name] = self.member_tmp_dic
                        print_comment("type_info.enum_list.append")
                        self.module_info.type_info.enum_list.append(enum_unit)

                        # init temp parameters and set the current handler to None
                        self.type_tmp_name = ""
                        self.member_tmp_dic = {}
                        self.current_handler = None
                        self.dic_temp = {}
                        self.current_state = ""
                        self.dic_str_temp = ""
                    else:
                        if line_left.find(',') > 0:
                            for dec in line_left.split(','):
                                if dec != "":
                                    self.dic_temp[dec] = self.type_tmp_name
                            self.current_state = "get_def_dics"
                        else:
                            self.crashed = True
                    return ""
                else:
                    line_left, result = eat_units(line_left, "{")
                    self.dic_str_temp += line_left
                    return ""
            # else:
            #     self.crashed = True
        return line_left

    def struct_analyzer(self, line_left):
        line = line_left
        line_left = line_left.strip()
        if self.compile_flag is True and line_left != "":
            if self.struct_in_getmember(line_left):
                return ""
            elif self.member_type_tmp != "":
                line_left = self.member_type_tmp
                self.member_type_tmp = ""

            # first time we call this function
            if self.current_state == "":
                if line_left != "":
                    if (line_left[-1] == ';'):
                        if line.find(' ')<0:
                            '''
                            forward struct declaration, don't care
                            '''
                            return ""
                        else:
                            return "struct " + line
                    line_left, result = kick_units(line_left, '{')
                    if line_left == "":
                        self.type_tmp_name = "struct"
                    else:
                        self.type_tmp_name = "struct" + " " + line_left

                    self.current_state = "get_struct_member"
                    self.current_handler = self.struct_analyzer
                    return ""
                else:
                    '''
                    struct
                    {
                        int a;
                        int b;
                    };
                    this is forbidden,
                    but may be you will use
                    struct
                    {
                        int a;
                        int b;
                    }c;
                    had better not do like that....

                    '''
                    self.crashed = True
                    return ""
            # seems we finish analyzed this struct
            elif line_left.strip()[0] == '}' or self.current_state == "get_def_dics":
                line_left, result = eat_units(line_left, "}")
                if (line_left[-1] == ';'):
                    print_comment("to do: e-data struct")
                    struct_unit = model.struct_info(
                        name=self.type_tmp_name,
                        is_public=False,
                        member_list=self.member_tmp_dic)
                    line_left = line_left[:-1]
                    if line_left != "":
                        if line_left.find(',') > 0:
                            for dec in line_left.split(','):
                                self.module_info.declaration_list.append(dec)
                        else:
                            self.module_info.declaration_list.append(line_left.strip())
                    # self.dic_temp[self.type_tmp_name] = self.member_tmp_dic
                    print_comment("type_info.struct_list.append")
                    self.module_info.type_info.struct_list.append(struct_unit)
                    self.module_info.type_info.type_def_list.update({self.type_tmp_name:''})

                    # init temp parameters and set the current handler to None
                    self.type_tmp_name = ""
                    self.member_tmp_dic = {}
                    self.current_handler = None
                    self.dic_temp = {}
                    self.current_state = ""
                else:
                    if line_left.find(',') > 0:
                        for dec in line_left.split(','):
                            if dec != "":
                                self.dic_temp[dec] = self.type_tmp_name
                        self.current_state = "get_def_dics"
                    else:
                        self.crashed = True
                return ""

            else:
                line_left, result = eat_units(line_left, "{")
                line_left = self.member_tmp_dic_update(line_left)

                if result is True:
                    return ""

        return line_left
    def union_analyzer(self, line_left):
        line_left = line_left.strip()
        if self.compile_flag is True:
            # first time we call this function
            if self.current_state == "":

                if line_left != "":
                    if (line_left[-1] == ';'):
                        '''
                        forward union declaration, don't care
                        '''
                        return ""
                    line_left, result = kick_units(line_left, '{')
                    if line_left == "":
                        self.type_tmp_name = "union"
                    else:
                        self.type_tmp_name = "union" + " " + line_left

                    self.current_state = "get_union_member"
                    self.current_handler = self.union_analyzer
                    return ""
                else:
                    self.crashed = True
                    return ""
            if line_left != "":
                # seems we finish analyzed this union
                if line_left.strip()[0] == '}' or self.current_state == "get_def_dics":
                    line_left, result = eat_units(line_left, "}")
                    if (line_left[-1] == ';'):
                        self.type_tmp_name = self.type_tmp_name + line_left[:-1]
                        if not self.dic_temp:
                            if self.type_tmp_name != line_left[:-1]:
                                typedef_dic = {
                                    line_left[:-1]: self.type_tmp_name
                                }
                                print_comment("type_info.type_def_list.update")
                                self.module_info.type_info.type_def_list.update(
                                    typedef_dic)
                        else:
                            if self.type_tmp_name != line_left[:-1]:
                                typedef_dic = {
                                    line_left[:-1]: self.type_tmp_name
                                }
                                print_comment("type_info.type_def_list.update")
                                self.module_info.type_info.type_def_list.update(
                                    typedef_dic)

                            for key, value in self.dic_temp.items():
                                print_comment("type_info.type_def_list.update")
                                self.module_info.type_info.type_def_list.update(
                                    {key: value})

                        union_unit = model.union_info(
                            name=self.type_tmp_name,
                            is_public=False,
                            union_list=self.union_tmp_list)

                        # self.dic_temp[self.type_tmp_name] = self.member_tmp_dic
                        print_comment("type_info.union_list.append")
                        self.module_info.type_info.union_list.append(
                            union_unit)

                        # init temp parameters and set the current handler to None
                        self.type_tmp_name = ""
                        self.member_tmp_dic = {}
                        self.union_tmp_list = []
                        self.current_handler = None
                        self.dic_temp = {}
                        self.current_state = ""
                    else:
                        if line_left.find(',') > 0:
                            for dec in line_left.split(','):
                                if dec != "":
                                    self.dic_temp[dec] = self.type_tmp_name
                            self.current_state = "get_def_dics"
                        else:
                            self.crashed = True
                    return ""

                else:
                    line_left, result = eat_units(line_left, "{")
                    if (line_left == ""):
                        return ""
                    line_left, result = eat_units(line_left, "}")
                    if result is True:
                        if line_left[-1] == ';' and self.member_tmp_dic != {}:
                            self.union_tmp_list.append(
                                {line_left[:-1]: self.member_tmp_dic})
                            self.member_tmp_dic = {}
                            return ""

                    line_left, reuslt, type_str = self.find_type(line_left)
                    if reuslt is True and line_left[-1] == ';':
                        self.member_tmp_dic[line_left[:-1]] = type_str
                        return ""
                    elif self.member_tmp_dic != {}:
                        self.union_tmp_list.append(self.member_tmp_dic)
                        self.member_tmp_dic = {}
                        return ""
                    elif line_left[-1] == ';':
                        line_left = line_left[:line_left.find(';')].strip() + ';'
                        ret = re.match(r'(.*)\s(.*);', line_left.strip())
                        if ret is not None:
                            self.union_tmp_list.append(
                                {ret.group(2): ret.group(1).strip()})
                        else:
                            self.crashed = True
                    else:
                        return ""
                    if result is True:
                        return ""

        return line_left

    '''
    7.type specifier:
        >>>>>>>>>>>>>
                    > base_type                     >
        > sign_flag >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
        >>>>>>>>>>>>> struct_list (struct spec)     >
        >>>>>>>>>>>>> enum
                         < ;             <
    '''
    def type_specifier(self, line_left):
        line_left, find_type_result, type_str = self.find_defined_type(line_left)
        line_left, result = kick_units(line_left, ";")
        if result is True:
            
            '''
            pointer solution typedef
            '''
            line_left, result = eat_units(line_left, "*")
            if result is True:
                type_str = type_str + '*'

            if type_str != line_left:
                typedef_dic = {line_left: type_str}
                print_comment("type_info.type_def_list.update")
                self.module_info.type_info.type_def_list.update(typedef_dic)
            return ""
        elif find_type_result is True:
            self.crashed = True
            return ""
        type_analyzer_list = {
            "struct": self.type_struct_analyzer,
            "union": self.type_union_analyzer,
            "enum": self.type_enum_analyzer
        }
        for key in type_analyzer_list.keys():
            line_left, result = eat_units(line_left, key)
            if result is True:
                self.brace_cnt_in_struct = 0
                self.member_type_tmp = ""
                line_left = type_analyzer_list[key](line_left)
                break
        return line_left

    def type_dec_list(self, line_left):
        print_comment("to do: enum struct directly define")
        return line_left

    '''
    3.type definition:
                    >>>>>>>>>>>>>>>>>>>>>
        > typedef   > type specifier    >  dec_list > ;
    '''
    def type_definition_analyze(self, line_left):
        if self.compile_flag is True and line_left != "":
            if self.current_state in self.type_state_handler_dic.keys():
                self.current_handler = self.type_state_handler_dic[self.current_state]
                return self.current_handler(line_left)
            if self.type_analyzer_handler is None:
                for type_analyzer in self.type_analyzer_dic.keys():
                    '''
                    judge if is enum or struct defined
                    '''
                    if (line_left.find("(") < 0 and line_left.find("{") > 0)  or type_analyzer == "typedef":
                        line_left, result = eat_units(line_left, type_analyzer)
                        if result is True:
                            self.type_analyzer_handler = self.type_analyzer_dic[
                                type_analyzer]
                            break
            if self.type_analyzer_handler is not None:
                line_left = self.type_analyzer_handler(line_left)
                self.type_analyzer_handler = None
        return line_left
